package cn.wind.xboot.module.app.v1.controller;

import cn.hutool.http.HttpUtil;
import cn.wind.xboot.auth.token.MyRedisTokenStore;
import cn.wind.xboot.core.res.ApiResult;
import cn.wind.xboot.logic.app.entity.AppVersion;
import cn.wind.xboot.logic.app.service.IAppAboutService;
import cn.wind.xboot.logic.app.service.IAppVersionService;
import cn.wind.xboot.logic.cli.entity.CliClient;
import cn.wind.xboot.logic.cli.entity.CliInfo;
import cn.wind.xboot.logic.cli.service.ICliClientService;
import cn.wind.xboot.logic.pf.entity.PfSms;
import cn.wind.xboot.logic.pf.service.IPfSmsService;
import cn.wind.klog.annotation.Log;
import cn.wind.klog.annotation.LogAround;
import cn.wind.klog.annotation.LogFilterType;
import cn.wind.xboot.core.utils.*;
import cn.wind.xboot.framework.constant.ActionConstant;
import cn.wind.xboot.framework.constant.ChannelConstant;
import cn.wind.xboot.framework.constant.ModuleConstant;
import cn.wind.xboot.module.app.v1.handler.AppMyLogHandler;
import cn.wind.xboot.module.app.v1.vo.AppAboutVo;
import cn.wind.xboot.module.app.v1.vo.AppVersionVo;
import cn.wind.xboot.module.app.v1.vo.SignUpVo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.google.common.collect.Sets;
import com.wind.encrypt.anno.Encrypt;
import com.wind.encrypt.anno.Secure;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.InvocationTargetException;
import java.security.Principal;
import java.util.Arrays;
import java.util.Map;

/**
 * <p>Title: AppOpenController</p>
 * <p>Description: TODO</p>
 *
 * @author xukk
 * @version 1.0
 * @date 2018/8/13
 */
@RestController
@RequestMapping("api/open")
@Secure(encrypt = @Encrypt(ignore = true))
public class AppOpenController extends BaseController{
    @Autowired
    private ICliClientService cliClientService;
    @Autowired
    private IPfSmsService pfSmsService;
    @Autowired
    private IAppVersionService appVersionService;
    @Autowired
    private IAppAboutService appAboutService;
    @Autowired(required = false)
    private MyRedisTokenStore redisTokenStore;

    @PostMapping("signIn")
    @LogAround
    @Log(module = ModuleConstant.USER,action = ActionConstant.LOGIN,
            channel = ChannelConstant.APP,
            pattern = "用户[#{#jsonObject[username]}]登录",
            extra = "#{#jsonObject[extra].toString()}",
            filterType = LogFilterType.ASPECTJ,fallback=AppMyLogHandler.class)
    public ApiResult signIn(@RequestBody JSONObject jsonObject,HttpServletRequest request) {
        hasNoBlank(jsonObject,Sets.newHashSet("username","password"));
        String username=jsonObject.getString("username");
        String password=jsonObject.getString("password");
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", "Basic YXBwOmFwcA==");
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
        //  也支持中文
        params.add("username", username);
        params.add("password", password);
        params.add("scope","app");
        params.add("grant_type","password");
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);
        ResponseEntity responseEntity= restTemplate.postForEntity(RequestUtil.getBasePath(request)+"/oauth/token", requestEntity, Map.class);
        Map<String,Object> result=(Map)responseEntity.getBody();
        if(redisTokenStore!=null){
            jsonObject.put("userId",currentUserId(redisTokenStore.readAuthentication(String.valueOf(result.getOrDefault("access_token",null)))));
        }
        return ApiResult.Custom().success().add(responseEntity.getBody());
    }
    private Long currentUserId(Principal principal) {
        if(principal instanceof OAuth2Authentication)
        {
            OAuth2Authentication OAuth2Authentication=(OAuth2Authentication)principal;
            if (OAuth2Authentication == null) {
                return 0L;
            }
            if (OAuth2Authentication.getUserAuthentication() == null) {
                return 0L;
            }
            if (OAuth2Authentication.getUserAuthentication().getPrincipal() == null) {
                return 0L;
            }
            try {
                Object object=OAuth2Authentication.getUserAuthentication().getPrincipal();
                if(object instanceof String){
                    return 0L;
                }
                return Long.valueOf(BeanUtil.getProperty(OAuth2Authentication.getUserAuthentication().getPrincipal(),"userId"));
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
        return 0L;
    }
/*    @PostMapping("signUp")
    @LogAround
    @Log(module = ModuleConstant.USER,action = ActionConstant.REGISTER,channel = ChannelConstant.APP,pattern = "用户[#{#jsonObject[mobile]}]注册",filterType = LogFilterType.ASPECTJ,fallback=AppMyLogHandler.class)
    public ApiResult signUp(@RequestBody JSONObject jsonObject){
        SignUpVo signUpVo= jsonObject.toJavaObject(SignUpVo.class);
        CliClient cliClient=cliClientService.findByUsername(signUpVo.getMobile());
        smsHelper.checkCode(signUpVo.getMobile(),signUpVo.getSmsCode());
        Assert.checkArgument(cliClient==null,"手机号已存在");
        ValidationUtil.validate(signUpVo);
        cliClient=new CliClient();
        CliInfo cliInfo=new CliInfo();
        cliClient.setPassword(PasswordUtil.encode(signUpVo.getPassword()));
        cliInfo.setMobile(signUpVo.getMobile());
        cliInfo.setNickName(signUpVo.getNickName());
        cliClient.setCliInfo(cliInfo);
        cliClient.setUsername(IdWorker.getIdStr());
        cliClient.setRandomFlag(true);
        cliClientService.save(cliClient);
        return ApiResult.Custom().success();
    }*/
/*    @LogAround
    @Log(module = ModuleConstant.USER,action = ActionConstant.FORGET,channel = ChannelConstant.APP,pattern = "用户[#{#jsonObject[mobile]}]修改密码",filterType = LogFilterType.ASPECTJ,fallback=AppMyLogHandler.class)
    @PostMapping("forget")
    public ApiResult forget(@RequestBody JSONObject jsonObject) {
        hasNoBlank(jsonObject, Sets.newHashSet("smsCode","mobile","newPass"));
        String smsCode=jsonObject.getString("smsCode");
        String mobile=jsonObject.getString("mobile");
        String password=jsonObject.getString("newPass");
        smsHelper.checkCode(mobile,smsCode);
        CliClient cliClient=cliClientService.findByUsername(mobile);
        Assert.checkNotNull(cliClient,"无效对象");
        cliClientService.updatePassword(cliClient.getId(), PasswordUtil.encode(password));
        return ApiResult.Custom().success();
    }*/

/*    @PostMapping(value = "sms")
    public ApiResult sms(@RequestBody JSONObject jsonObject, HttpServletRequest request){
        hasNoBlank(jsonObject,Sets.newHashSet("mobile","type"));
        String mobile=jsonObject.getString("mobile");
        String type=jsonObject.getString("type");
        PfSms pfSms=pfSmsService.getOne(new QueryWrapper<PfSms>().lambda().eq(PfSms::getName,type));
        Assert.checkNotNull(pfSms,"无法根据type获取实例");
        smsManage.build(mobile,pfSms,true, HttpUtil.getClientIP(request));
        return ApiResult.Custom().success();
    }*/

    @GetMapping(value = "ad")
    public ApiResult ad(@RequestBody JSONObject jsonObject){
       return ApiResult.Custom().success();
    }


    @PostMapping(value = "version")
    public ApiResult version(@RequestBody JSONObject jsonObject){
        hasNoBlank(jsonObject,Sets.newHashSet("platform","currentVersion"));
        String platform=jsonObject.getString("platform");
        String currentVersion=jsonObject.getString("currentVersion");
        String[] arr=currentVersion.split("\\.");
        Assert.checkArgument(arr.length==3&& MathUtil.isDigitalLessThan(arr),"版本信息格式错误(xx.xx.xx)");
        AppVersion appVersion= appVersionService.getOne(new QueryWrapper<AppVersion>().eq("platform",platform).orderBy(true,false,new String[]{"create_time"}));
        Assert.checkNotNull(appVersion,"无版本信息");
        String[] minVersion=appVersion.getMinVersion().split("\\.");
        String[] latestVersion=appVersion.getLastestVersion().split("\\.");
        Assert.checkArgument(minVersion.length==3&& MathUtil.isDigitalLessThan(minVersion),"最小版本信息格式错误");
        Assert.checkArgument(latestVersion.length==3&& MathUtil.isDigitalLessThan(latestVersion),"最新版本信息格式错误");
        StringBuffer curBuff=new StringBuffer();
        StringBuffer minBuff=new StringBuffer();
        StringBuffer latestBuff=new StringBuffer();
        Arrays.stream(arr).forEach(v->curBuff.append(StringUtils.leftPad(v,3,"0")));
        Arrays.stream(minVersion).forEach(v->minBuff.append(StringUtils.leftPad(v,3,"0")));
        Arrays.stream(latestVersion).forEach(v->latestBuff.append(StringUtils.leftPad(v,3,"0")));
        Integer curValue=Integer.valueOf(curBuff.toString());
        Integer minValue=Integer.valueOf(minBuff.toString());
        Integer latestValue=Integer.valueOf(latestBuff.toString());
        if(curValue<latestValue){
            appVersion.setUpdateFlag(true);
        }
        if(curValue<minValue){
            appVersion.setForceUpdate(true);
        }
        if(currentVersion.equalsIgnoreCase(appVersion.getForceVersion())){
            appVersion.setForceUpdate(true);
        }
        return ApiResult.Custom().success().add(beanMapper.map(appVersion, AppVersionVo.class));
    }

    @GetMapping(value = "about")
    public ApiResult about() {
        return ApiResult.Custom().success().add(mapList(appAboutService.list(new QueryWrapper<>()),AppAboutVo.class));
    }

}
